import { IHttpResponse, RuntimeModelError } from '@ibiz-template/core';
import { INavigateParamContainer, IPicker } from '@ibiz/model-core';
import {
  CodeListItem,
  convertNavData,
  FormItemController,
  getDeACMode,
  SearchFormController,
} from '@ibiz-template/runtime';

/**
 * 表单搜索项控制器
 *
 * @export
 * @class FormSearchItemController
 * @extends {FormItemController}
 */
export class FormSearchItemController extends FormItemController {
  /**
   * 表单控制器
   *
   * @type {SearchFormController}
   * @memberof FormSearchItemController
   */
  declare readonly form: SearchFormController;

  /**
   * 编辑器参数集合
   *
   * @type {IData}
   * @memberof FormSearchItemController
   */
  public editorParams: IData = {};

  /**
   * 排序
   *
   * @type {(string | undefined)}
   * @memberof FormSearchItemController
   */
  public sort: string | undefined = '';

  /**
   * 文本属性
   *
   * @type {string}
   * @memberof FormSearchItemController
   */
  public textName: string = 'srfmajortext';

  /**
   * 主键属性
   *
   * @type {string}
   * @memberof FormSearchItemController
   */
  public keyName: string = 'srfkey';

  /**
   * 选中数据
   *
   * @type {IData[]}
   * @memberof FormSearchItemController
   */
  public selectItems: IData[] = [];

  /**
   * 远程数据
   *
   * @type {IData[]}
   * @memberof FormSearchItemController
   */
  public remoteDatas: IData[] = [];

  /**
   * 初始化
   *
   * @protected
   * @return {*}  {Promise<void>}
   * @memberof FormSearchItemController
   */
  protected async onInit(): Promise<void> {
    await super.onInit();
    await this.initEditorParams();
    await this.loadData('');
  }

  /**
   * 初始化编辑器参数
   *
   * @memberof FormSearchItemController
   */
  protected async initEditorParams() {
    const editor: IPicker | undefined = this.model.editor;
    if (editor) {
      if (editor.editorParams) {
        Object.keys(editor.editorParams).forEach(key => {
          this.editorParams[key] = editor.editorParams![key];
        });
      }
      if (editor.appDataEntityId && editor.appDEACModeId) {
        const deACMode = await getDeACMode(
          editor.appDEACModeId,
          editor.appDataEntityId,
          this.context.srfappid,
        );
        if (deACMode) {
          // 自填模式相关
          const { minorSortAppDEFieldId, minorSortDir } = deACMode;
          if (minorSortAppDEFieldId && minorSortDir) {
            this.sort = `${minorSortAppDEFieldId.toLowerCase()},${minorSortDir.toLowerCase()}`;
          }
          if (deACMode.textAppDEFieldId) {
            this.textName = deACMode.textAppDEFieldId;
          }
          if (deACMode.valueAppDEFieldId) {
            this.keyName = deACMode.valueAppDEFieldId;
          }
        }
      }
    }
  }

  /**
   * 加载数据
   *
   * @param {string} query 搜索条件
   * @memberof FormSearchItemController
   */
  async loadData(query: string) {
    try {
      const codeListItems = await this.loadCodeList(this.editorParams.codeList);
      const codeListGroup = await this.loadCodeList(
        this.editorParams.codeListGroup,
      );
      const res = await this.getServiceData(query, this.data);
      this.remoteDatas = this.handleDataItems(
        res.data,
        codeListItems,
        codeListGroup,
      );
    } catch (error) {
      throw new RuntimeModelError(this.model, '加载数据错误');
    }
  }

  /**
   * 处理数据
   *
   * @protected
   * @param {IData[]} dataItems
   * @param {readonly} codeListItems
   * @param {*} CodeListItem
   * @param {*} []
   * @memberof FormSearchItemController
   */
  protected handleDataItems(
    dataItems: IData[],
    codeListItems: readonly CodeListItem[],
    codeListGroup: readonly CodeListItem[],
  ) {
    let items: IData[] = [];
    let groupItems: IData[] = [];
    if (codeListItems.length > 0 && dataItems.length > 0) {
      const resultMap: IData = {};
      const resultKeys: number[] = [];
      dataItems.forEach((item: IData) => {
        const index = codeListItems.findIndex((codeItem: CodeListItem) =>
          Object.is(codeItem.value, item[this.keyName]),
        );
        if (index !== -1) {
          Object.assign(item, { [this.textName]: codeListItems[index].text });
          Object.assign(resultMap, { [index]: item });
          resultKeys.push(index);
        }
      });
      resultKeys.sort((a, b) => a - b);
      const result: IData[] = [];
      resultKeys.forEach((value: number) => {
        if (resultMap[value]) {
          result.push(resultMap[value]);
        }
      });
      items = result;
    } else {
      items = dataItems;
    }
    const groupField = this.editorParams.groupField;
    if (codeListGroup.length > 0 && groupField) {
      codeListGroup.forEach((codeItem: CodeListItem) => {
        groupItems.push({
          id: codeItem.value,
          text: codeItem.text,
          isGroup: true,
          expand: false,
          children: [],
        });
      });
      groupItems.forEach(group => {
        const children = items.filter(item => item[groupField] === group.id);
        Object.assign(group, {
          children: [...children],
        });
      });
    } else {
      groupItems = [...items];
    }
    return groupItems;
  }

  /**
   * 处理选中数据
   *
   * @param {IData[]} selectDatas
   * @memberof FormSearchItemController
   */
  handleSelectData(selectDatas: IData[]) {
    const selectKeys: string[] = [];
    selectDatas.forEach((selected: IData) => {
      selectKeys.push(selected[this.keyName]);
    });
    this.setDataValue(selectKeys.length > 0 ? selectKeys.join(',') : '');
    this.form.search();
  }

  /**
   *  设置选中数据
   *
   * @param {IData[]} selectDatas
   * @memberof FormSearchItemController
   */
  setSelectItems(selectDatas: IData[]) {
    if (selectDatas && selectDatas.length > 0) {
      selectDatas.forEach((item: IData) => {
        Object.assign(item, {
          formitem_name: this.model.codeName,
        });
      });
    }
    this.selectItems = selectDatas;
  }

  /**
   *  设置选中数据
   *
   * @memberof FormSearchItemController
   */
  getSelectItems() {
    return this.selectItems;
  }

  /**
   *  清除选中项
   *
   * @memberof FormSearchItemController
   */
  clearSelectItems() {
    this.selectItems = [];
  }

  /**
   * 公共参数处理
   *
   * @param {IData} data
   * @param {IContext} context
   * @param {IParams} params
   * @return {*}  {{ context: IContext; params: IParams }}
   * @memberof FormSearchItemController
   */
  protected handlePublicParams(
    data: IData,
    context: IContext,
    params: IParams,
  ): { context: IContext; params: IParams } {
    const { navigateContexts, navigateParams } = this.model
      .editor as INavigateParamContainer;
    let selfContext = {};
    if (navigateContexts && data) {
      selfContext = convertNavData(navigateContexts!, data, params, context);
    }
    const _context = Object.assign(context.clone(), selfContext);

    let selfParams = {};
    if (navigateParams && data) {
      selfParams = convertNavData(navigateParams!, data, params, context);
    }
    return { context: _context, params: selfParams };
  }

  /**
   * 获取实体数据集数据
   *
   * @param {string} query
   * @param {IData} data
   * @return {*}  {Promise<IHttpResponse<IData[]>>}
   * @memberof FormSearchItemController
   */
  protected async getServiceData(
    query: string,
    data: IData,
  ): Promise<IHttpResponse<IData[]>> {
    // 附加编辑器视图参数
    const editor: IPicker = this.model.editor as IPicker;
    if (editor) {
      const { context, params } = this.handlePublicParams(
        data,
        this.context,
        this.params,
      );
      Object.assign(params, {
        size: 1000,
      });
      if (query) {
        Object.assign(params, { query });
      }
      if (this.sort && !Object.is(this.sort, '')) {
        Object.assign(params, { sort: this.sort });
      }
      if (editor.appDataEntityId && editor.appDEDataSetId) {
        const app = ibiz.hub.getApp(this.context.srfappid);
        const res = await app.deService.exec(
          editor.appDataEntityId,
          editor.appDEDataSetId,
          context,
          params,
        );
        return res as IHttpResponse<IData[]>;
      }
      throw new RuntimeModelError(this.model, '请配置实体和实体数据集');
    }
    throw new RuntimeModelError(this.model, '请配置数据选择编辑器');
  }

  /**
   * 加载代码表数据
   *
   * @protected
   * @param {string} [codeList]
   * @return {*}  {Promise<readonly}
   * @memberof FormSearchItemController
   */
  protected async loadCodeList(
    codeList?: string,
  ): Promise<readonly CodeListItem[]> {
    let dataItems: readonly CodeListItem[] = [];
    if (codeList) {
      const app = await ibiz.hub.getApp(this.context.srfappid);
      dataItems = await app.codeList.get(codeList, this.context, {});
    }
    return dataItems;
  }
}
